package com.app.framework;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.log4j.PropertyConfigurator;

import com.app.annotation.Column;
import com.app.annotation.Table;
import com.app.config.DCacheConfig;
import com.app.framework.orm.StorableModel;
import com.app.framework.util.IdxUtil;
import com.app.framework.util.ReflectionUtil;
import com.app.framework.util.StringUtils;
import com.app.framework.util.helper.ClassInfo;
import com.app.framework.util.helper.FieldInfo;
import com.app.model.ColumnInfo;
import com.app.model.TableInfo;
import com.app.store.AbstractMySqlStore;
import com.app.store.ColumnStore;
import com.app.store.StoreFactory;
import com.app.util.ClassTableUtil;
import com.app.util.ClassUtil;

public abstract class AbstractServer {

	static {
		PropertyConfigurator.configure(System.getProperty("user.dir") + "/log4j.properties");//指定log4j的位置
		initStore();
	}
	
	@SuppressWarnings("unchecked")
	private static void initStore() {
		DCacheConfig dc = DCacheConfig.getInstance();
		String base = dc.getTableScanBasePakage();
		Map<String,Class<?>> classes = ClassUtil.getClassesByAnnotation(base, Table.class);
		List<TableInfo> tableInfos = new ArrayList<TableInfo>();
		for(Class<?> clz : classes.values()) {
			ClassInfo classInfo = ReflectionUtil.getClassInfo(clz);
			TableInfo tableInfo = new TableInfo();
			String tableName = clz.getName().replace(".", "_");
			Table t = clz.getAnnotation(Table.class);
			if(!StringUtils.isNullOrEmpty(t.name())) {
				tableName = t.name();
			}
			tableInfo.setTableName(tableName);
			for(FieldInfo fieldInfo : classInfo.getPersistFields().values()) {
				ColumnInfo colInfo = new ColumnInfo();
				String columnName = fieldInfo.getField().getName();
				int length = Column.LENGTH;
				boolean nullable = Column.NULLABLE;
				String def = Column.DEFAULT;
				boolean index = classInfo.getIndexFields().containsKey(fieldInfo.getField().getName());
				boolean idx = classInfo.getIdField().getField().getName().equals(fieldInfo.getField().getName());
				if(fieldInfo.getField().isAnnotationPresent(Column.class)) {
					Column c = fieldInfo.getField().getAnnotation(Column.class);
					if(!StringUtils.isNullOrEmpty(c.name())) {
						columnName = c.name();
						length = c.length();
						def = c.Default();
						nullable = c.nullable();
					}
				}
				String type = ClassTableUtil.transTableColumnType(fieldInfo.getField().getType(), length);
				colInfo.setDef(def);
				colInfo.setIndex(index);
				colInfo.setKey(idx);
				colInfo.setName(columnName);
				if(idx) {
					nullable = false;
				}
				colInfo.setNullable(nullable);
				colInfo.setType(type);
				tableInfo.addColInfo(colInfo);
				if(colInfo.isKey()) {
					tableInfo.setKey(colInfo);
				}
			}
			ClassTableUtil.cacheClassNameToTableName(clz, tableName);
			Collections.reverse(tableInfo.getColInfos());
			tableInfo.addColInfo(ColumnInfo.LAST_TIME);
			tableInfos.add(tableInfo);
		}
		ColumnStore cs = StoreFactory.newColumnStore();
		if(AbstractMySqlStore.class.isAssignableFrom(cs.getClass())) {
			AbstractMySqlStore mysql = (AbstractMySqlStore)cs;
			mysql.initTables(tableInfos);
			for(Class<?> clz : classes.values()) {
				IdxUtil.initId((Class<? extends StorableModel>)clz);
			}
		}
	}
}
